package com.dc.docs._888_面试.concurrent._9_synchronized;

/**
 * Description: Synchronized 修饰实例方法_错误实例
 * @author: gdc
 * @date: 2021/6/17
 * @version 1.0
 */
public class SyncObjBadDemo implements Runnable {

    /**
     * 共享资源
     */
    private static int num = 0;
    /**
     * 实例变量
     */
    //private int num = 0;

    /**
     * 增加方法
     * synchronized修饰实例方法，当前线程的锁是实例对象 -> accountingSync
     * 当一个线程正在访问一个对象的 synchronized实例方法，那么其他线程不能访问该对象的其他 synchronized 方法
     * 原因：一个对象只有一把锁
     */
    public synchronized void increase(){
        num++;
    }

    @Override
    public void run() {
        for (int z = 0; z < 10000; z++) {
            increase();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        SyncObjBadDemo obj1 = new SyncObjBadDemo();
        SyncObjBadDemo obj2 = new SyncObjBadDemo();

        /**
         * 两个线程修饰了不同的实例
         *
         * thread1 访问实例对象obj1的synchronized方法，thread2访问实例对象obj2的synchronized方法
         * 这样是允许的，因为两个实例对象的锁并不相同
         * 此时，如果两个线程操作的数据非共享，线程安全有保证；
         *      如果数据共享，线程安全无法保证
         */
        Thread thread1 = new Thread(obj1);
        Thread thread2 = new Thread(obj2);

        thread1.start();
        thread2.start();

        // join()方法：表示调用线程等待该线程完成后，才能继续向下运行
        // 下面的案例可以理解：main线程需要等待 thread1、thread2线程执行完之后，才能执行
        thread1.join();
        thread2.join();

        System.out.println(num);

        //System.out.println(obj1.num);
        //System.out.println(obj2.num);
    }
}
